package com.maschinenstuermer.profiler.config;

import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import com.maschinenstuermer.profiler.config.impl.Config;

public class ConfigFactory {
	private static final Logger logger = Logger.getLogger(ConfigFactory.class
			.getName());

	private static List<String> SELF_EXCLUDES = Arrays.asList(new String[] {
		"com.maschinenstuermer.profiler.*",
		"com.maschinenstuermer.profiler.config.**",
		"com.maschinenstuermer.profiler.model.**",
		"com.maschinenstuermer.profiler.timer.**",
		"com.maschinenstuermer.profiler.timer.transform.**"
	});
	private static Config instance;

	private ConfigFactory() {
	}

	public static void load(String fileName) throws IOException, Exception {
		FileReader fileReader = new FileReader(fileName);
		try {
			JAXBContext context = JAXBContext.newInstance(Config.class);
			Unmarshaller unmarshaller = context.createUnmarshaller();
			instance = (Config) unmarshaller.unmarshal(fileReader);
			instance.getExcludes().addAll(getSelfExcludes());
		} finally {
			fileReader.close();
		}
	}

	public static boolean profileClass(String clazzName) {
		boolean matchesIncludedClasses = 
			instance.getIncludedClasses().matcher(clazzName).matches();
		boolean matchesExcludedClasses = 
			instance.getExcludedClasses().matcher(clazzName).matches();
		boolean result = matchesIncludedClasses && !matchesExcludedClasses;
		
		if (result) {
			logger.info("profilingClass:" + clazzName);
		}
		return result;
	}
	
	public static List<String> getSelfExcludes() {
		return SELF_EXCLUDES;
	}

	/**
	 * Required for tests!
	 */
	public static Config resetInstance() {
		instance = null;
		return instance();
	}
	
	public synchronized static Config instance() {
		if (instance == null) {
			instance = new Config();
			instance.addInclude("**");
			instance.addExclude("java.**");
			instance.getExcludes().addAll(getSelfExcludes());
		}
		return instance;
	}
}
